--[[-------------------------------------------------------------------------
  James Whitehead II grants anyone the right to use this work for any purpose,
  without any conditions, unless such conditions are required by law.
---------------------------------------------------------------------------]]

local major = "DongleStub"
local minor = tonumber(string.match("$Revision: 204 $", "(%d+)") or 1)

local g = getfenv(0)

if not g.DongleStub or g.DongleStub:IsNewerVersion(major, minor) then
	local lib = setmetatable({}, {
		__call = function(t,k) 
			if type(t.versions) == "table" and t.versions[k] then 
				return t.versions[k].instance
			else
				error("Cannot find a library with name '"..tostring(k).."'", 2)
			end
		end
	})

	function lib:IsNewerVersion(major, minor)
		local entry = self.versions and self.versions[major]
		
		if not entry then return true end
		local oldmajor,oldminor = entry.instance:GetVersion()
		
		return minor > oldminor
	end

	function lib:ReplaceInstance(old,new)
		for k,v in pairs(old) do old[k] = nil end
		for k,v in pairs(new) do old[k] = v end
	end
	
	function lib:Register(newInstance)
		local major,minor = newInstance:GetVersion()
		if not self:IsNewerVersion(major, minor) then return false end
		
		local versionData = self.versions[major]
		if not versionData then
			-- New major version
			versionData = {
				instance = newInstance,
				old = {},
			}
			
			self.versions[major] = versionData
			newInstance:Activate(self)
			return newInstance
		end
		
		local oldInstance = versionData.instance
		local oldList = versionData.old
		versionData.instance = newInstance
				
		-- Deactivate the old libary if necessary
		if oldInstance and type(oldInstance.Deactivate) == "function" then
			oldInstance:Deactivate(self, oldList, newInstance) 
		end
		
		local skipCopy = newInstance:Activate(self, oldInstance, oldList)
		table.insert(oldList, oldInstance)
		if not skipCopy then
			for i,old in ipairs(oldList) do
				self:ReplaceInstance(old, newInstance)
			end
		end
	end

	function lib:GetVersion() return major,minor end

	function lib:Activate(stub, old, oldList)
		if old then 
			self.versions = old.versions
		else
			self.versions = {}
		end
		g.DongleStub = self
	end
	
	-- Actually trigger libary activation here
	local stub = g.DongleStub or lib
	stub:Register(lib)
end
